This document aims at exploring the dataset of 9 southern-individuals in 2014. For that purpose, we need first to load the weanlingNES package to load data.
# load library
library(weanlingNES)
# load data
# data("data_ses", package = "weanlingNES")
load("../data/data_ses.rda")
Let’s have a look at what’s inside data_ses$data_2014:
# list structure
str(data_ses$year_2014, max.level = 1, give.attr = F, no.list = T)
## $ ind_140059:Classes 'data.table' and 'data.frame': 2309 obs. of 35 variables:
## $ ind_140060:Classes 'data.table' and 'data.frame': 1873 obs. of 35 variables:
## $ ind_140062:Classes 'data.table' and 'data.frame': 2619 obs. of 35 variables:
## $ ind_140063:Classes 'data.table' and 'data.frame': 1575 obs. of 35 variables:
## $ ind_140068:Classes 'data.table' and 'data.frame': 1908 obs. of 35 variables:
## $ ind_140069:Classes 'data.table' and 'data.frame': 2129 obs. of 35 variables:
## $ ind_140072:Classes 'data.table' and 'data.frame': 2641 obs. of 35 variables:
## $ ind_140073:Classes 'data.table' and 'data.frame': 1693 obs. of 35 variables:
## $ ind_140075:Classes 'data.table' and 'data.frame': 1460 obs. of 35 variables:
A list of 9 data.frames, one for each seal
For convenience, we aggregate all 9 individuals into one dataset.
# combine all individuals
data_2014 <- rbindlist(data_ses$year_2014)
# display
DT::datatable(data_2014[sample.int(.N, 10), ], options = list(scrollX = T))
Table 1: Sample of 10 random rows from data_2014
Summary
# raw_data
data_2014[, .(
nb_days_recorded = uniqueN(as.Date(date)),
nb_dives = .N,
maxdepth_mean = mean(maxdepth),
dduration_mean = mean(dduration),
botttime_mean = mean(botttime),
pdi_mean = mean(pdi, na.rm = T)
), by = .id] %>%
sable(
caption = "Summary diving information relative to each 2018 individual",
digits = 2
)
Table 2: Summary diving information relative to each 2018 individual
|
.id
|
nb_days_recorded
|
nb_dives
|
maxdepth_mean
|
dduration_mean
|
botttime_mean
|
pdi_mean
|
|
ind_140059
|
239
|
2309
|
215.04
|
747.36
|
392.75
|
8581.81
|
|
ind_140060
|
190
|
1873
|
187.45
|
577.07
|
267.79
|
8302.87
|
|
ind_140062
|
264
|
2619
|
147.84
|
559.74
|
296.52
|
8645.40
|
|
ind_140063
|
159
|
1575
|
173.56
|
609.74
|
304.83
|
8035.70
|
|
ind_140068
|
193
|
1908
|
164.44
|
658.23
|
332.77
|
8309.80
|
|
ind_140069
|
213
|
2129
|
172.52
|
544.39
|
256.49
|
8241.80
|
|
ind_140072
|
265
|
2641
|
171.04
|
564.46
|
241.13
|
8412.04
|
|
ind_140073
|
176
|
1693
|
189.39
|
614.60
|
275.40
|
8284.61
|
|
ind_140075
|
141
|
1460
|
131.59
|
462.81
|
192.98
|
7971.23
|
Some explanatory plots
Missing values
# build dataset to check for missing values
dataPlot <- melt(data_2014[, .(.id, is.na(.SD)), .SDcol = -c(
".id",
"divenumber",
"year",
"month",
"day",
"hour",
"min",
"sec",
"juldate",
"divetype",
"date"
# "phase",
# "lat",
# "lon"
)])
# add the id of rows
dataPlot[, id_row := c(1:.N), by = c("variable", ".id")]
# plot
ggplot(dataPlot, aes(x = variable, y = id_row, fill = value)) +
geom_tile() +
labs(x = "Attributes", y = "Rows") +
scale_fill_manual(
values = c("white", "black"),
labels = c("Real", "Missing")
) +
facet_wrap(.id ~ ., scales = "free_y") +
theme_jjo() +
theme(
legend.position = "top",
axis.text.x = element_text(angle = 45, hjust = 1),
legend.key = element_rect(colour = "black")
)
Let’s look closer to the variables with missing values:
# table with percent
table_inter <- data_2014[, lapply(.SD, function(x) {
round(length(x[is.na(x)]) * 100 / length(x), 1)
}), .SDcol = -c(
".id",
"divenumber",
"year",
"month",
"day",
"hour",
"min",
"sec",
"juldate",
"divetype",
"date"
# "phase",
# "lat",
# "lon"
)]
# find which are different from 0
cond_inter <- sapply(table_inter, function(x) {
x == 0
})
# display the percentages that are over 0
table_inter[, which(cond_inter) := NULL] %>%
sable(caption = "Percentage of missing values per columns having missing values!") %>%
scroll_box(width = "100%")
Table 3: Percentage of missing values per columns having missing values!
|
driftrate
|
benthicdivevertrate
|
cornerindex
|
foragingindex
|
verticalspeed90perc
|
verticalspeed95perc
|
|
1
|
24.2
|
67.7
|
0.5
|
0.8
|
0.8
|
Nothing bad, missing values seem to occur only in column we are not interested in.
Outliers
Let’s see if we have some outliers. Some of them are quiet easy to spot looking at the distribution of dive duration:
# plot that, weirdly, doesn't free x axis...
# ggplot(
# melt(data_2014,
# id.vars = c(".id"),
# measure.vars = c("dduration","maxdepth","driftrate")),
# aes(x = value, fill = .id)
# ) +
# geom_histogram(show.legend = FALSE) +
# facet_grid(variable ~ .id,
# scales = "free"
# ) +
# labs(y = "# of dives") +
# theme_jjo()
ggplot(
melt(data_2014,
id.vars = c(".id"),
measure.vars = c("dduration")
),
aes(x = value, fill = .id)
) +
geom_histogram(show.legend = FALSE) +
facet_grid(variable ~ .id,
scales = "free"
) +
labs(y = "# of dives") +
theme_jjo() +
theme(
axis.title.x = element_blank(),
text = element_text(size = 8)
)
ggplot(
melt(data_2014,
id.vars = c(".id"),
measure.vars = c("maxdepth")
),
aes(x = value, fill = .id)
) +
geom_histogram(show.legend = FALSE) +
facet_grid(variable ~ .id,
scales = "free"
) +
labs(y = "# of dives") +
theme_jjo() +
theme(
strip.text.x = element_blank(),
axis.title.x = element_blank(),
text = element_text(size = 8)
)
ggplot(
melt(data_2014,
id.vars = c(".id"),
measure.vars = c("driftrate")
),
aes(x = value, fill = .id)
) +
geom_histogram(show.legend = FALSE) +
facet_grid(variable ~ .id,
scales = "free"
) +
labs(y = "# of dives") +
theme_jjo() +
theme(
strip.text.x = element_blank(),
text = element_text(size = 8)
)
Nothing that obvious, which is great :)
All Variables
names_display <- names(data_2014[, -c(
".id",
"date",
"divenumber",
"year",
"month",
"day",
"hour",
"min",
"sec",
"juldate",
"divetype",
# "euphoticdepth",
# "thermoclinedepth",
"day_departure" # ,
# "phase",
# "lat",
# "lon",
# "dist_dep"
)])
# calulate the median of driftrate for each day
median_driftrate <- data_2014[divetype == "2: drift",
.(driftrate = quantile(driftrate, 0.5)),
by = .(date = as.Date(date), .id)
]
# let's identity when the smooth changes sign
changes_driftrate <- median_driftrate %>%
.[, .(
y_smooth = predict(loess(driftrate ~ as.numeric(date), span = 0.25)),
date
), by = .id] %>%
.[c(FALSE, diff(sign(y_smooth)) != 0), ]
Full trip duration
for (i in names_display) {
cat("#####", i, "{.unlisted .unnumbered} \n")
if (i == "driftrate") {
print(
ggplot(
data = melt(data_2014[, .(.id, date, get(i), divetype)],
id.vars = c(".id", "date", "divetype")
),
aes(
x = as.Date(date),
y = value,
col = divetype
)
) +
geom_point(
alpha = 1 / 10,
size = .5
) +
geom_vline(
data = changes_driftrate,
aes(xintercept = date),
linetype = 2
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = "Drift Rate m/s", col = "Dive Type") +
theme_jjo() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom"
) +
guides(colour = guide_legend(override.aes = list(
size = 7,
alpha = 1
)))
)
} else {
print(
ggplot(
data = melt(data_2014[, .(.id, date, get(i))],
id.vars = c(".id", "date")
),
aes(
x = as.Date(date),
y = value,
col = .id
)
) +
geom_point(
show.legend = FALSE,
alpha = 1 / 10,
size = .5
) +
geom_vline(
data = changes_driftrate,
aes(xintercept = date),
linetype = 2
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = i) +
theme_jjo() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
)
}
cat("\n \n")
}
The vertical dashed lines represent changes in buoyancy (see vignette("buoyancy_detect") for more information)
maxdepth

dduration

botttime

desctime

descrate

asctime

ascrate

pdi

dwigglesdesc

dwigglesbott

dwigglesasc

totvertdistbot

bottrange

efficiency

idz

driftdiveindex

driftrate

benthicdiveindex

benthicdivevertrate

cornerindex

foragingindex

verticalspeed90perc

verticalspeed95perc

First month at sea
for (i in names_display) {
# subtitle
cat("#####", i, "{.unlisted .unnumbered} \n")
# print plot
print(
ggplot(
data = melt(data_2014[day_departure < 32,
.(.id, day_departure, get(i))],
id.vars = c(".id", "day_departure")),
aes(
x = day_departure,
y = value,
color = .id,
group = day_departure
)
) +
geom_boxplot(
show.legend = FALSE,
alpha = 1 / 10,
size = .5
) +
facet_wrap(. ~ .id, scales = "free") +
labs(x = "# days since departure", y = i) +
theme_jjo()
)
cat("\n \n")
}
maxdepth

dduration

botttime

desctime

descrate

asctime

ascrate

pdi

dwigglesdesc

dwigglesbott

dwigglesasc

totvertdistbot

bottrange

efficiency

idz

driftdiveindex

driftrate

benthicdiveindex

benthicdivevertrate

cornerindex

foragingindex

verticalspeed90perc

verticalspeed95perc

Dive Type
# dataset to plot proportional area plot
data_2014[, sum_id := .N, by = .(.id, day_departure)] %>%
.[, sum_id_days := .N, by = .(.id, day_departure, divetype)] %>%
.[, prop := sum_id_days / sum_id]
dataPlot <- unique(data_2014[, .(prop, .id, divetype, day_departure)])
# area plot
ggplot(dataPlot, aes(
x = as.numeric(day_departure),
y = prop,
fill = as.character(divetype)
)) +
geom_area(alpha = 0.6, size = 1) +
facet_wrap(.id ~ ., scales = "free") +
theme_jjo() +
theme(legend.position = "bottom") +
labs(x = "# of days since departure",
y = "Proportion of dives",
fill = "Dive types")
Drift Rate
In the following graphs:
driftrate is calculated using only divetype == "2: drift"
- whereas all the others variables are calculated all dives considered
- Dives were
driftrate > 0 were excluded
# build dataset
dataPlot <- data_2014[divetype == "2: drift" &
driftrate < 0,
# median drift rate for drift dive
.(driftrate = median(driftrate, na.rm = T)),
by = .(.id, day_departure)] %>%
# merge to get other parameters including all dives
.[data_2014[driftrate < 0,
.(
# median dive duration all dives considered
dduration = median(dduration, na.rm = T),
# median max depth all dives considered
maxdepth = median(maxdepth, na.rm = T),
# median bottom dives all dives considered
botttime = median(botttime, na.rm = T)
),
by = .(.id, day_departure)],
on = c(".id", "day_departure")]
# plot
ggplot(dataPlot, aes(x = botttime, y = driftrate, col = .id)) +
geom_point(size = .5, alpha = .5) +
geom_smooth(method = "lm") +
guides(color = "none") +
facet_wrap(.id ~ .) +
scale_x_continuous(limits = c(0, 700)) +
labs(x = "Daily median Bottom time (s)",
y = "Daily median drift rate (m.s-1)") +
theme_jjo()
# plot
ggplot(dataPlot, aes(x = maxdepth, y = driftrate, col = .id)) +
geom_point(size = .5, alpha = .5) +
geom_smooth(method = "lm") +
guides(color = "none") +
facet_wrap(.id ~ .) +
labs(x = "Daily median Maximum depth (m)",
y = "Daily median drift rate (m.s-1)") +
theme_jjo()
# plot
ggplot(dataPlot, aes(x = dduration, y = driftrate, col = .id)) +
geom_point(size = .5, alpha = .5) +
geom_smooth(method = "lm") +
guides(color = "none") +
facet_wrap(.id ~ .) +
labs(x = "Daily median Dive duration (s)",
y = "Daily median drift rate (m.s-1)") +
theme_jjo()
Behavioral Aerobic Dive Limit (bADL)
Based on Shero et al. (2018), we decided to look at the bADL as the 95th percentile of dive duration each day, for those with \(n \geq 8\). This threshold was chosen following this figure, please note that this number is particularly low cause only one dive every 2.2 hours was sampled:
ggplot(data_2014[,.(nb_dives = .N),
by = .(.id, day_departure)],
aes(x=nb_dives, fill=.id)) +
geom_histogram(show.legend = FALSE) +
facet_wrap(.~.id) +
labs(y="# of days", x = "# of dives per day") +
theme_jjo() +
theme(text = element_text(size = 8))
# select day that have at least 50 dives
days_to_keep = data_2014[,
.(nb_dives = .N),
by = .(.id, day_departure)] %>%
.[nb_dives >= 8,]
# keep only those days
data_2014_complete_day = merge(data_2014,
days_to_keep,
by = c(".id", "day_departure"))
# data plot
dataPlot = data_2014_complete_day[divetype=="1: foraging",
.(badl = quantile(dduration, 0.95)),
by = .(.id, day_departure)]
# combine two datasets to be able to use a second axis
# https://stackoverflow.com/questions/49185583/two-y-axes-with-different-scales-for-two-datasets-in-ggplot2
dataMegaPlot = rbind(data_2014_complete_day[divetype == "2: drift"] %>%
.[, .(w = .id,
y = driftrate,
x = day_departure,
z = "second_plot")],
dataPlot[, .(
w = .id,
# tricky one
y = (badl / 1000) - 1,
x = day_departure,
z = "first_plot"
)])
# plot
ggplot() +
geom_point(
data = dataMegaPlot[z == "second_plot", ],
aes(x = x, y = y),
alpha = 1 / 10,
size = 0.5,
color = "grey40",
show.legend = FALSE
) +
geom_path(data = dataMegaPlot[z == "first_plot", ],
aes(x = x, y = y, color = w),
show.legend = FALSE) +
scale_y_continuous(
# Features of the first axis
name = "Drift rate (m/s)",
# Add a second axis and specify its features
sec.axis = sec_axis( ~ (. * 1000) + 1000,
name = "Behavioral Aerobic Dive Limit (s)")
) +
labs(x = "# days since departure") +
facet_wrap(w ~ .) +
theme_jjo()
Looking at this graph, I want to believe that there is some kind of relationship between the bADL as defined by Shero et al. (2018) and the drift rate (and so buyoancy).
# get badl
dataplot_1 = data_2014_complete_day[,
.(badl = quantile(dduration, 0.95)),
by = .(.id, day_departure)]
# get driftrate
dataplot_2 = data_2014_complete_day[divetype == "2: drift",
.(driftrate = median(driftrate)),
by = .(.id, day_departure)]
# merge
dataPlot = merge(dataplot_1,
dataplot_2,
by = c(".id", "day_departure"),
all = TRUE)
# plot
ggplot(data = dataPlot[driftrate < 0, ],
aes(x = badl, y = driftrate, col = .id)) +
geom_point(show.legend = FALSE) +
geom_smooth(method = "lm", show.legend = FALSE) +
facet_wrap(.id~., scales = "free") +
labs(x = "Behavioral Aerobic Dive Limit (s)",
y = "Drift rate (m/s)") +
theme_jjo()

LS0tCnRpdGxlOiAiRGF0YSBFeHBsb3JhdGlvbiBTRVMgLSAyMDE0IgphdXRob3I6ICJKb2ZmcmV5IEpPVU1BQSIKZGF0ZTogImByIGludmlzaWJsZShTeXMuc2V0bG9jYWxlKGxvY2FsZSA9ICdDJykpOyBmb3JtYXQoU3lzLkRhdGUoKSwgZm9ybWF0ID0gJyVCICVkLCAlWScpYCIKb3V0cHV0OgogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIGNzczogY29zbW9fY3VzdG9tLmNzcwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZGZfcHJpbnQ6IGRlZmF1bHQKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB5ZXMKICAgICAgc21vb3RoX3Njcm9sbDogbm8KdmlnbmV0dGU6ID4KICAlXFZpZ25ldHRlSW5kZXhFbnRyeXtEYXRhIEV4cGxvcmF0aW9uIFNFUyAtIDIwMTR9CiAgJVxWaWduZXR0ZUVuZ2luZXtrbml0cjo6cm1hcmtkb3dufQogICVcVmlnbmV0dGVFbmNvZGluZ3tVVEYtOH0KLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb21tYW5kIHRvIGJ1aWxkIHBhY2thZ2Ugd2l0aG91dCBnZXR0aW5nIHZpZ25ldHRlIGVycm9yCiMgaHR0cHM6Ly9naXRodWIuY29tL3JzdHVkaW8vcmVudi9pc3N1ZXMvODMzCiMgZGV2dG9vbHM6OmNoZWNrKGJ1aWxkX2FyZ3M9YygiLS1uby1idWlsZC12aWduZXR0ZXMiKSkKCiMgcmVkdWNlIHBuZyBzaXplCmtuaXRyOjprbml0X2hvb2tzJHNldChvcHRpcG5nID0ga25pdHI6Omhvb2tfb3B0aXBuZykKa25pdHI6OmtuaXRfaG9va3Mkc2V0KHBuZ3F1YW50ID0ga25pdHI6Omhvb2tfcG5ncXVhbnQpCgojIGdsb2JhbCBvcHRpb24gcmVsYXRpdmUgdG8gcm1hcmtkb3duCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gVFJVRSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBvdXQud2lkdGggPSAiMTAwJSIsCiAgbWVzc2FnZSA9IEZBTFNFLAogIHdhcm5pbmcgPSBGQUxTRSwKICAjIHRpZHkgPSBUUlVFLAogIGNhY2hlLmxhenkgPSBGQUxTRSwKICBvcHRpcG5nID0gIi1vNyAtcXVpZXQiLAogIHBuZ3F1YW50ID0gIi0tc3BlZWQ9MSIKKQoKIyBsaWJyYXJ5CmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShrYWJsZUV4dHJhKQoKIyByZW1vdmUgc29tZSB3YXJuaW5ncwpzdXBwcmVzc1dhcm5pbmdzKGxpYnJhcnkoZ2dwbG90MikpCgojIGRlZmluZSBteSBvd24gdGFibGUgZm9ybWF0OiBodHRwczovL2dpdGh1Yi5jb20vaGFvemh1MjMzL2thYmxlRXh0cmEvaXNzdWVzLzM3NApzYWJsZSA8LSBmdW5jdGlvbih4LCBlc2NhcGUgPSBULCAuLi4pIHsKICBrbml0cjo6a2FibGUoeCwgZXNjYXBlID0gZXNjYXBlLCAuLi4pICU+JQogICAga2FibGVfc3R5bGluZygKICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgInJlc3BvbnNpdmUiKSwKICAgICAgZnVsbF93aWR0aCA9IEYKICAgICkKfQoKIyB0aGVtZSBnZ3Bsb3QKIyBiYXNlZDogaHR0cHM6Ly9iZW5qYW1pbmxvdWlzLXN0YXQuZnIvZW4vYmxvZy8yMDIwLTA1LTIxLWFzdHVjZXMtZ2dwbG90LXJtYXJrZG93bi8KdGhlbWVfampvIDwtIGZ1bmN0aW9uKGJhc2Vfc2l6ZSA9IDEyKSB7CiAgdGhlbWVfYncoYmFzZV9zaXplID0gYmFzZV9zaXplKSAlK3JlcGxhY2UlCiAgICB0aGVtZSgKICAgICAgIyB0aGUgd2hvbGUgZmlndXJlCiAgICAgICMgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEpLCBmYWNlID0gImJvbGQiLCBtYXJnaW4gPSBtYXJnaW4oMCwwLDUsMCksIGhqdXN0ID0gMCksCiAgICAgICMgZmlndXJlIGFyZWEKICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgICAjIGF4ZXMKICAgICAgIyBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC44NSksIGZhY2UgPSAiYm9sZCIpLAogICAgICAjIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuNzApLCBmYWNlID0gImJvbGQiKSwKICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG9yID0gImJsYWNrIiwgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMiwgImxpbmVzIiksIHR5cGUgPSAiY2xvc2VkIikpLAogICAgICAjIGxlZ2VuZAogICAgICAjIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuODUpLCBmYWNlID0gImJvbGQiKSwKICAgICAgIyBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuNzApLCBmYWNlID0gImJvbGQiKSwKICAgICAgIyBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICMgbGVnZW5kLmtleS5zaXplID0gdW5pdCgxLjUsICJsaW5lcyIpLAogICAgICAjIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAidHJhbnNwYXJlbnQiLCBjb2xvdXIgPSBOQSksCiAgICAgICMgTGVzIDxVKzAwRTk+dGlxdWV0dGVzIGRhbnMgbGUgY2FzIGQndW4gZmFjZXR0aW5nCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjODg4ODg4IiwgY29sb3IgPSAiIzg4ODg4OCIpLAogICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC44NSksIGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gIndoaXRlIiwgbWFyZ2luID0gbWFyZ2luKDUsIDAsIDUsIDApKQogICAgKQp9CmBgYAoKVGhpcyBkb2N1bWVudCBhaW1zIGF0IGV4cGxvcmluZyB0aGUgZGF0YXNldCBvZiA5IHNvdXRoZXJuLWluZGl2aWR1YWxzIGluIDIwMTQuIEZvciB0aGF0IHB1cnBvc2UsIHdlIG5lZWQgZmlyc3QgdG8gbG9hZCB0aGUgYHdlYW5saW5nTkVTYCBwYWNrYWdlIHRvIGxvYWQgZGF0YS4KCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0xfQojIGxvYWQgbGlicmFyeQpsaWJyYXJ5KHdlYW5saW5nTkVTKQoKIyBsb2FkIGRhdGEKIyBkYXRhKCJkYXRhX3NlcyIsIHBhY2thZ2UgPSAid2VhbmxpbmdORVMiKQpsb2FkKCIuLi9kYXRhL2RhdGFfc2VzLnJkYSIpCmBgYAoKTGV04oCZcyBoYXZlIGEgbG9vayBhdCB3aGF04oCZcyBpbnNpZGUgYGRhdGFfc2VzJGRhdGFfMjAxNGA6CiAgCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0yfQojIGxpc3Qgc3RydWN0dXJlCnN0cihkYXRhX3NlcyR5ZWFyXzIwMTQsIG1heC5sZXZlbCA9IDEsIGdpdmUuYXR0ciA9IEYsIG5vLmxpc3QgPSBUKQpgYGAKCj4gQSBsaXN0IG9mIGByIGxlbmd0aChkYXRhX3NlcyR5ZWFyXzIwMTQpYCBgZGF0YS5mcmFtZXNgLCBvbmUgZm9yIGVhY2ggc2VhbAoKRm9yIGNvbnZlbmllbmNlLCB3ZSBhZ2dyZWdhdGUgYWxsIGByIGxlbmd0aChkYXRhX3NlcyR5ZWFyXzIwMTQpYCBpbmRpdmlkdWFscyBpbnRvIG9uZSBkYXRhc2V0LgoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTMsIGV2YWw9RkFMU0V9CiMgY29tYmluZSBhbGwgaW5kaXZpZHVhbHMKZGF0YV8yMDE0IDwtIHJiaW5kbGlzdChkYXRhX3NlcyR5ZWFyXzIwMTQpCgojIGRpc3BsYXkKRFQ6OmRhdGF0YWJsZShkYXRhXzIwMTRbc2FtcGxlLmludCguTiwgMTApLCBdLCBvcHRpb25zID0gbGlzdChzY3JvbGxYID0gVCkpCmBgYApgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtNCwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CiMgY29tYmluZSBhbGwgaW5kaXZpZHVhbHMKZGF0YV8yMDE0IDwtIHJiaW5kbGlzdChkYXRhX3NlcyR5ZWFyXzIwMTQpCgojIHRpdGxlCmNhdCgiPHRhYmxlIHN0eWxlPSd3aWR0aDogNTAlJz4iLAogIHBhc3RlMCgKICAgICI8Y2FwdGlvbj4iLAogICAgIigjdGFiOm15RFRodG1sdG9vbHMpIiwKICAgICJTYW1wbGUgb2YgMTAgcmFuZG9tIHJvd3MgZnJvbSBgZGF0YV8yMDE0YCIsCiAgICAiPC9jYXB0aW9uPiIKICApLAogICI8L3RhYmxlPiIsCiAgc2VwID0gIlxuIgopCgojIGRpc3BsYXkKRFQ6OmRhdGF0YWJsZShkYXRhXzIwMTRbc2FtcGxlLmludCguTiwgMTApLCBdLCBvcHRpb25zID0gbGlzdChzY3JvbGxYID0gVCkpCmBgYAoKIyMgU3VtbWFyeQoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTV9CiMgcmF3X2RhdGEKZGF0YV8yMDE0WywgLigKICBuYl9kYXlzX3JlY29yZGVkID0gdW5pcXVlTihhcy5EYXRlKGRhdGUpKSwKICBuYl9kaXZlcyA9IC5OLAogIG1heGRlcHRoX21lYW4gPSBtZWFuKG1heGRlcHRoKSwKICBkZHVyYXRpb25fbWVhbiA9IG1lYW4oZGR1cmF0aW9uKSwKICBib3R0dGltZV9tZWFuID0gbWVhbihib3R0dGltZSksCiAgcGRpX21lYW4gPSBtZWFuKHBkaSwgbmEucm0gPSBUKQopLCBieSA9IC5pZF0gJT4lCiAgc2FibGUoCiAgICBjYXB0aW9uID0gIlN1bW1hcnkgZGl2aW5nIGluZm9ybWF0aW9uIHJlbGF0aXZlIHRvIGVhY2ggMjAxOCBpbmRpdmlkdWFsIiwKICAgIGRpZ2l0cyA9IDIKICApCmBgYAoKIyMgU29tZSBleHBsYW5hdG9yeSBwbG90cwoKIyMjIE1pc3NpbmcgdmFsdWVzCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtNiwgZmlnLmNhcD0iQ2hlY2sgZm9yIG1pc3NpbmcgdmFsdWUgaW4gMjAxOC1pbmRpdmlkdWFscyIsIGZpZy53aWR0aD05fQojIGJ1aWxkIGRhdGFzZXQgdG8gY2hlY2sgZm9yIG1pc3NpbmcgdmFsdWVzCmRhdGFQbG90IDwtIG1lbHQoZGF0YV8yMDE0WywgLiguaWQsIGlzLm5hKC5TRCkpLCAuU0Rjb2wgPSAtYygKICAiLmlkIiwKICAiZGl2ZW51bWJlciIsCiAgInllYXIiLAogICJtb250aCIsCiAgImRheSIsCiAgImhvdXIiLAogICJtaW4iLAogICJzZWMiLAogICJqdWxkYXRlIiwKICAiZGl2ZXR5cGUiLAogICJkYXRlIgogICMgInBoYXNlIiwKICAjICJsYXQiLAogICMgImxvbiIKKV0pCiMgYWRkIHRoZSBpZCBvZiByb3dzCmRhdGFQbG90WywgaWRfcm93IDo9IGMoMTouTiksIGJ5ID0gYygidmFyaWFibGUiLCAiLmlkIildCgojIHBsb3QKZ2dwbG90KGRhdGFQbG90LCBhZXMoeCA9IHZhcmlhYmxlLCB5ID0gaWRfcm93LCBmaWxsID0gdmFsdWUpKSArCiAgZ2VvbV90aWxlKCkgKwogIGxhYnMoeCA9ICJBdHRyaWJ1dGVzIiwgeSA9ICJSb3dzIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKAogICAgdmFsdWVzID0gYygid2hpdGUiLCAiYmxhY2siKSwKICAgIGxhYmVscyA9IGMoIlJlYWwiLCAiTWlzc2luZyIpCiAgKSArCiAgZmFjZXRfd3JhcCguaWQgfiAuLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIHRoZW1lX2pqbygpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsYWNrIikKICApCmBgYAoKTGV0J3MgbG9vayBjbG9zZXIgdG8gdGhlIHZhcmlhYmxlcyB3aXRoIG1pc3NpbmcgdmFsdWVzOgoKYGBge3J9CiMgdGFibGUgd2l0aCBwZXJjZW50CnRhYmxlX2ludGVyIDwtIGRhdGFfMjAxNFssIGxhcHBseSguU0QsIGZ1bmN0aW9uKHgpIHsKICByb3VuZChsZW5ndGgoeFtpcy5uYSh4KV0pICogMTAwIC8gbGVuZ3RoKHgpLCAxKQp9KSwgLlNEY29sID0gLWMoCiAgIi5pZCIsCiAgImRpdmVudW1iZXIiLAogICJ5ZWFyIiwKICAibW9udGgiLAogICJkYXkiLAogICJob3VyIiwKICAibWluIiwKICAic2VjIiwKICAianVsZGF0ZSIsCiAgImRpdmV0eXBlIiwKICAiZGF0ZSIKICAjICJwaGFzZSIsCiAgIyAibGF0IiwKICAjICJsb24iCildCgojIGZpbmQgd2hpY2ggYXJlIGRpZmZlcmVudCBmcm9tIDAKY29uZF9pbnRlciA8LSBzYXBwbHkodGFibGVfaW50ZXIsIGZ1bmN0aW9uKHgpIHsKICB4ID09IDAKfSkKCiMgZGlzcGxheSB0aGUgcGVyY2VudGFnZXMgdGhhdCBhcmUgb3ZlciAwCnRhYmxlX2ludGVyWywgd2hpY2goY29uZF9pbnRlcikgOj0gTlVMTF0gJT4lCiAgc2FibGUoY2FwdGlvbiA9ICJQZXJjZW50YWdlIG9mIG1pc3NpbmcgdmFsdWVzIHBlciBjb2x1bW5zIGhhdmluZyBtaXNzaW5nIHZhbHVlcyEiKSAlPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiKQpgYGAKCk5vdGhpbmcgYmFkLCBtaXNzaW5nIHZhbHVlcyBzZWVtIHRvIG9jY3VyIG9ubHkgaW4gY29sdW1uIHdlIGFyZSBub3QgaW50ZXJlc3RlZCBpbi4KCiMjIyBPdXRsaWVycwoKTGV04oCZcyBzZWUgaWYgd2UgaGF2ZSBzb21lIG91dGxpZXJzLiBTb21lIG9mIHRoZW0gYXJlIHF1aWV0IGVhc3kgdG8gc3BvdCBsb29raW5nIGF0IHRoZSBkaXN0cmlidXRpb24gb2YgZGl2ZSBkdXJhdGlvbjoKCmBgYHtyIGZpZy5jYXA9IkRpc3RyaWJ1dGlvbiBvZiBgZGR1cmF0aW9uYCwgYG1heGRlcHRoYCBhbmQgYGRyaWZ0cmF0ZWAgZm9yIGVhY2ggc2VhbCIsIGZpZy5zaG93ID0gImhvbGQiLCBmaWcuaGVpZ2h0PTEuNX0KIyBwbG90IHRoYXQsIHdlaXJkbHksIGRvZXNuJ3QgZnJlZSB4IGF4aXMuLi4KIyBnZ3Bsb3QoCiMgICBtZWx0KGRhdGFfMjAxNCwKIyAgICAgICAgaWQudmFycyA9IGMoIi5pZCIpLAojICAgICAgICBtZWFzdXJlLnZhcnMgPSBjKCJkZHVyYXRpb24iLCJtYXhkZXB0aCIsImRyaWZ0cmF0ZSIpKSwKIyAgIGFlcyh4ID0gdmFsdWUsIGZpbGwgPSAuaWQpCiMgKSArCiMgICBnZW9tX2hpc3RvZ3JhbShzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiMgICBmYWNldF9ncmlkKHZhcmlhYmxlIH4gLmlkLAojICAgICAgICAgICAgICBzY2FsZXMgPSAiZnJlZSIKIyAgICkgKwojICAgbGFicyh5ID0gIiMgb2YgZGl2ZXMiKSArCiMgICB0aGVtZV9qam8oKQpnZ3Bsb3QoCiAgbWVsdChkYXRhXzIwMTQsCiAgICBpZC52YXJzID0gYygiLmlkIiksCiAgICBtZWFzdXJlLnZhcnMgPSBjKCJkZHVyYXRpb24iKQogICksCiAgYWVzKHggPSB2YWx1ZSwgZmlsbCA9IC5pZCkKKSArCiAgZ2VvbV9oaXN0b2dyYW0oc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGZhY2V0X2dyaWQodmFyaWFibGUgfiAuaWQsCiAgICBzY2FsZXMgPSAiZnJlZSIKICApICsKICBsYWJzKHkgPSAiIyBvZiBkaXZlcyIpICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUoCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KQogICkKZ2dwbG90KAogIG1lbHQoZGF0YV8yMDE0LAogICAgaWQudmFycyA9IGMoIi5pZCIpLAogICAgbWVhc3VyZS52YXJzID0gYygibWF4ZGVwdGgiKQogICksCiAgYWVzKHggPSB2YWx1ZSwgZmlsbCA9IC5pZCkKKSArCiAgZ2VvbV9oaXN0b2dyYW0oc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGZhY2V0X2dyaWQodmFyaWFibGUgfiAuaWQsCiAgICBzY2FsZXMgPSAiZnJlZSIKICApICsKICBsYWJzKHkgPSAiIyBvZiBkaXZlcyIpICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KQogICkKZ2dwbG90KAogIG1lbHQoZGF0YV8yMDE0LAogICAgaWQudmFycyA9IGMoIi5pZCIpLAogICAgbWVhc3VyZS52YXJzID0gYygiZHJpZnRyYXRlIikKICApLAogIGFlcyh4ID0gdmFsdWUsIGZpbGwgPSAuaWQpCikgKwogIGdlb21faGlzdG9ncmFtKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBmYWNldF9ncmlkKHZhcmlhYmxlIH4gLmlkLAogICAgc2NhbGVzID0gImZyZWUiCiAgKSArCiAgbGFicyh5ID0gIiMgb2YgZGl2ZXMiKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKAogICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkKICApCmBgYAoKTm90aGluZyB0aGF0IG9idmlvdXMsIHdoaWNoIGlzIGdyZWF0IDopCgojIyMgQWxsIFZhcmlhYmxlcwoKYGBge3J9Cm5hbWVzX2Rpc3BsYXkgPC0gbmFtZXMoZGF0YV8yMDE0WywgLWMoCiAgIi5pZCIsCiAgImRhdGUiLAogICJkaXZlbnVtYmVyIiwKICAieWVhciIsCiAgIm1vbnRoIiwKICAiZGF5IiwKICAiaG91ciIsCiAgIm1pbiIsCiAgInNlYyIsCiAgImp1bGRhdGUiLAogICJkaXZldHlwZSIsCiAgIyAiZXVwaG90aWNkZXB0aCIsCiAgIyAidGhlcm1vY2xpbmVkZXB0aCIsCiAgImRheV9kZXBhcnR1cmUiICMgLAogICMgInBoYXNlIiwKICAjICJsYXQiLAogICMgImxvbiIsCiAgIyAiZGlzdF9kZXAiCildKQoKIyBjYWx1bGF0ZSB0aGUgbWVkaWFuIG9mIGRyaWZ0cmF0ZSBmb3IgZWFjaCBkYXkKbWVkaWFuX2RyaWZ0cmF0ZSA8LSBkYXRhXzIwMTRbZGl2ZXR5cGUgPT0gIjI6IGRyaWZ0IiwKICAuKGRyaWZ0cmF0ZSA9IHF1YW50aWxlKGRyaWZ0cmF0ZSwgMC41KSksCiAgYnkgPSAuKGRhdGUgPSBhcy5EYXRlKGRhdGUpLCAuaWQpCl0KCiMgbGV0J3MgaWRlbnRpdHkgd2hlbiB0aGUgc21vb3RoIGNoYW5nZXMgc2lnbgpjaGFuZ2VzX2RyaWZ0cmF0ZSA8LSBtZWRpYW5fZHJpZnRyYXRlICU+JQogIC5bLCAuKAogICAgeV9zbW9vdGggPSBwcmVkaWN0KGxvZXNzKGRyaWZ0cmF0ZSB+IGFzLm51bWVyaWMoZGF0ZSksIHNwYW4gPSAwLjI1KSksCiAgICBkYXRlCiAgKSwgYnkgPSAuaWRdICU+JQogIC5bYyhGQUxTRSwgZGlmZihzaWduKHlfc21vb3RoKSkgIT0gMCksIF0KYGBgCgojIyMjIEZ1bGwgdHJpcCBkdXJhdGlvbgoKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1UUlVFfQpmb3IgKGkgaW4gbmFtZXNfZGlzcGxheSkgewogIGNhdCgiIyMjIyMiLCBpLCAiey51bmxpc3RlZCAudW5udW1iZXJlZH0gXG4iKQogIGlmIChpID09ICJkcmlmdHJhdGUiKSB7CiAgICBwcmludCgKICAgICAgZ2dwbG90KAogICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxNFssIC4oLmlkLCBkYXRlLCBnZXQoaSksIGRpdmV0eXBlKV0sCiAgICAgICAgICBpZC52YXJzID0gYygiLmlkIiwgImRhdGUiLCAiZGl2ZXR5cGUiKQogICAgICAgICksCiAgICAgICAgYWVzKAogICAgICAgICAgeCA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICB5ID0gdmFsdWUsCiAgICAgICAgICBjb2wgPSBkaXZldHlwZQogICAgICAgICkKICAgICAgKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIGFscGhhID0gMSAvIDEwLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgZ2VvbV92bGluZSgKICAgICAgICAgIGRhdGEgPSBjaGFuZ2VzX2RyaWZ0cmF0ZSwKICAgICAgICAgIGFlcyh4aW50ZXJjZXB0ID0gZGF0ZSksCiAgICAgICAgICBsaW5ldHlwZSA9IDIKICAgICAgICApICsKICAgICAgICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogICAgICAgIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICAgICAgICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiRHJpZnQgUmF0ZSBtL3MiLCBjb2wgPSAiRGl2ZSBUeXBlIikgKwogICAgICAgIHRoZW1lX2pqbygpICsKICAgICAgICB0aGVtZSgKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIgogICAgICAgICkgKwogICAgICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdCgKICAgICAgICAgIHNpemUgPSA3LAogICAgICAgICAgYWxwaGEgPSAxCiAgICAgICAgKSkpCiAgICApCiAgfSBlbHNlIHsKICAgIHByaW50KAogICAgICBnZ3Bsb3QoCiAgICAgICAgZGF0YSA9IG1lbHQoZGF0YV8yMDE0WywgLiguaWQsIGRhdGUsIGdldChpKSldLAogICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsICJkYXRlIikKICAgICAgICApLAogICAgICAgIGFlcygKICAgICAgICAgIHggPSBhcy5EYXRlKGRhdGUpLAogICAgICAgICAgeSA9IHZhbHVlLAogICAgICAgICAgY29sID0gLmlkCiAgICAgICAgKQogICAgICApICsKICAgICAgICBnZW9tX3BvaW50KAogICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgICAgICAgIGFscGhhID0gMSAvIDEwLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgZ2VvbV92bGluZSgKICAgICAgICAgIGRhdGEgPSBjaGFuZ2VzX2RyaWZ0cmF0ZSwKICAgICAgICAgIGFlcyh4aW50ZXJjZXB0ID0gZGF0ZSksCiAgICAgICAgICBsaW5ldHlwZSA9IDIKICAgICAgICApICsKICAgICAgICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogICAgICAgIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlbS8lWSIpICsKICAgICAgICBsYWJzKHggPSAiRGF0ZSIsIHkgPSBpKSArCiAgICAgICAgdGhlbWVfampvKCkgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCiAgICApCiAgfQoKICBjYXQoIlxuIFxuIikKfQpgYGAKClRoZSB2ZXJ0aWNhbCBkYXNoZWQgbGluZXMgcmVwcmVzZW50IGNoYW5nZXMgaW4gYnVveWFuY3kgKHNlZSBgdmlnbmV0dGUoImJ1b3lhbmN5X2RldGVjdCIpYCBmb3IgbW9yZSBpbmZvcm1hdGlvbikKCiMjIyMgey51bmxpc3RlZCAudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKYGBge3IgcmVzdWx0cz0nYXNpcycsIGNhY2hlPVRSVUUsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9N30KZm9yIChpIGluIG5hbWVzX2Rpc3BsYXkpIHsKICBjYXQoIiMjIyMjIiwgaSwgInsudW5saXN0ZWQgLnVubnVtYmVyZWR9IFxuIikKICBpZiAoaSA9PSAiZHJpZnRyYXRlIikgewogICAgcHJpbnQoCiAgICAgIGdncGxvdCgKICAgICAgICBkYXRhID0gbWVsdChkYXRhXzIwMTRbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpLCBkaXZldHlwZSldLAogICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsICJkYXRlIiwgImRpdmV0eXBlIikKICAgICAgICApLAogICAgICAgIGFlcygKICAgICAgICAgIHggPSBhcy5EYXRlKGRhdGUpLAogICAgICAgICAgeSA9IHZhbHVlLAogICAgICAgICAgY29sID0gZGl2ZXR5cGUKICAgICAgICApCiAgICAgICkgKwogICAgICAgIGdlb21fcG9pbnQoCiAgICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIGdlb21fdmxpbmUoCiAgICAgICAgICBkYXRhID0gY2hhbmdlc19kcmlmdHJhdGUsCiAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IGRhdGUpLAogICAgICAgICAgbGluZXR5cGUgPSAyCiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJW0vJVkiKSArCiAgICAgICAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIkRyaWZ0IFJhdGUgbS9zIiwgY29sID0gIkRpdmUgVHlwZSIpICsKICAgICAgICB0aGVtZV9qam8oKSArCiAgICAgICAgdGhlbWUoCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIKICAgICAgICApICsKICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICAgICAgICBzaXplID0gNywKICAgICAgICAgIGFscGhhID0gMQogICAgICAgICkpKQogICAgKQogIH0gZWxzZSB7CiAgICBwcmludCgKICAgICAgZ2dwbG90KAogICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxNFssIC4oLmlkLCBkYXRlLCBnZXQoaSkpXSwKICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLCAiZGF0ZSIpCiAgICAgICAgKSwKICAgICAgICBhZXMoCiAgICAgICAgICB4ID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgIGNvbCA9IC5pZAogICAgICAgICkKICAgICAgKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIGdlb21fdmxpbmUoCiAgICAgICAgICBkYXRhID0gY2hhbmdlc19kcmlmdHJhdGUsCiAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IGRhdGUpLAogICAgICAgICAgbGluZXR5cGUgPSAyCiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJW0vJVkiKSArCiAgICAgICAgbGFicyh4ID0gIkRhdGUiLCB5ID0gaSkgKwogICAgICAgIHRoZW1lX2pqbygpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQogICAgKQogIH0KCiAgY2F0KCJcbiBcbiIpCn0KYGBgCgojIyMjIEZpcnN0IG1vbnRoIGF0IHNlYQoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTE4LCBldmFsPUZBTFNFLCBpbmNsdWRlPVRSVUV9CmZvciAoaSBpbiBuYW1lc19kaXNwbGF5KSB7CiAgIyBzdWJ0aXRsZQogIGNhdCgiIyMjIyMiLCBpLCAiey51bmxpc3RlZCAudW5udW1iZXJlZH0gXG4iKQogIAogICMgcHJpbnQgcGxvdAogIHByaW50KAogICAgICBnZ3Bsb3QoCiAgICAgICAgZGF0YSA9IG1lbHQoZGF0YV8yMDE0W2RheV9kZXBhcnR1cmUgPCAzMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKC5pZCwgZGF5X2RlcGFydHVyZSwgZ2V0KGkpKV0sIAogICAgICAgICAgICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLCAiZGF5X2RlcGFydHVyZSIpKSwKICAgICAgICBhZXMoCiAgICAgICAgICB4ID0gZGF5X2RlcGFydHVyZSwKICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgIGNvbG9yID0gLmlkLAogICAgICAgICAgZ3JvdXAgPSBkYXlfZGVwYXJ0dXJlCiAgICAgICAgKQogICAgICApICsKICAgICAgICBnZW9tX2JveHBsb3QoCiAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgICAgICAgYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICBzaXplID0gLjUKICAgICAgICApICsKICAgICAgICBmYWNldF93cmFwKC4gfiAuaWQsIHNjYWxlcyA9ICJmcmVlIikgKwogICAgICAgIGxhYnMoeCA9ICIjIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwgeSA9IGkpICsKICAgICAgICB0aGVtZV9qam8oKQogICAgKQogIGNhdCgiXG4gXG4iKQp9CmBgYAoKIyMjIyB7LnVubGlzdGVkIC51bm51bWJlcmVkIC50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMTksIHJlc3VsdHM9J2FzaXMnLCBjYWNoZT1UUlVFLCBlY2hvPUZBTFNFfQpmb3IgKGkgaW4gbmFtZXNfZGlzcGxheSkgewogICMgc3VidGl0bGUKICBjYXQoIiMjIyMjIiwgaSwgInsudW5saXN0ZWQgLnVubnVtYmVyZWR9IFxuIikKICAKICAjIHByaW50IHBsb3QKICBwcmludCgKICAgICAgZ2dwbG90KAogICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxNFtkYXlfZGVwYXJ0dXJlIDwgMzIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLiguaWQsIGRheV9kZXBhcnR1cmUsIGdldChpKSldLCAKICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gYygiLmlkIiwgImRheV9kZXBhcnR1cmUiKSksCiAgICAgICAgYWVzKAogICAgICAgICAgeCA9IGRheV9kZXBhcnR1cmUsCiAgICAgICAgICB5ID0gdmFsdWUsCiAgICAgICAgICBjb2xvciA9IC5pZCwKICAgICAgICAgIGdyb3VwID0gZGF5X2RlcGFydHVyZQogICAgICAgICkKICAgICAgKSArCiAgICAgICAgZ2VvbV9ib3hwbG90KAogICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgICAgICAgIGFscGhhID0gMSAvIDEwLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBsYWJzKHggPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIsIHkgPSBpKSArCiAgICAgICAgdGhlbWVfampvKCkKICAgICkKICBjYXQoIlxuIFxuIikKfQpgYGAKCiMjIERpdmUgVHlwZQoKYGBge3IgZmlnLmNhcCA9ICJFdm9sdXRpb24gb2YgZGl2ZSB0eXBlIHByb3BvcnRpb24ifQojIGRhdGFzZXQgdG8gcGxvdCBwcm9wb3J0aW9uYWwgYXJlYSBwbG90CmRhdGFfMjAxNFssIHN1bV9pZCA6PSAuTiwgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSldICU+JQogIC5bLCBzdW1faWRfZGF5cyA6PSAuTiwgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSwgZGl2ZXR5cGUpXSAlPiUKICAuWywgcHJvcCA6PSBzdW1faWRfZGF5cyAvIHN1bV9pZF0KZGF0YVBsb3QgPC0gdW5pcXVlKGRhdGFfMjAxNFssIC4ocHJvcCwgLmlkLCBkaXZldHlwZSwgZGF5X2RlcGFydHVyZSldKQoKIyBhcmVhIHBsb3QKZ2dwbG90KGRhdGFQbG90LCBhZXMoCiAgeCA9IGFzLm51bWVyaWMoZGF5X2RlcGFydHVyZSksCiAgeSA9IHByb3AsCiAgZmlsbCA9IGFzLmNoYXJhY3RlcihkaXZldHlwZSkKKSkgKwogIGdlb21fYXJlYShhbHBoYSA9IDAuNiwgc2l6ZSA9IDEpICsKICBmYWNldF93cmFwKC5pZCB+IC4sIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lX2pqbygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIGxhYnMoeCA9ICIjIG9mIGRheXMgc2luY2UgZGVwYXJ0dXJlIiwgCiAgICAgICB5ID0gIlByb3BvcnRpb24gb2YgZGl2ZXMiLCAKICAgICAgIGZpbGwgPSAiRGl2ZSB0eXBlcyIpCmBgYAoKIyMgRHJpZnQgUmF0ZQoKPiBJbiB0aGUgZm9sbG93aW5nIGdyYXBoczoKPgo+ICogYGRyaWZ0cmF0ZWAgaXMgY2FsY3VsYXRlZCB1c2luZyBvbmx5IGBkaXZldHlwZSA9PSAiMjogZHJpZnQiYAo+ICogd2hlcmVhcyBhbGwgdGhlIG90aGVycyB2YXJpYWJsZXMgYXJlIGNhbGN1bGF0ZWQgYWxsIGRpdmVzIGNvbnNpZGVyZWQKPiAqIERpdmVzIHdlcmUgYGRyaWZ0cmF0ZSA+IDBgIHdlcmUgZXhjbHVkZWQKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0yOX0KIyBidWlsZCBkYXRhc2V0CmRhdGFQbG90IDwtIGRhdGFfMjAxNFtkaXZldHlwZSA9PSAiMjogZHJpZnQiICYKICAgICAgICAgICAgICAgICAgICAgICAgZHJpZnRyYXRlIDwgMCwKICAgICAgICAgICAgICAgICAgICAgICMgbWVkaWFuIGRyaWZ0IHJhdGUgZm9yIGRyaWZ0IGRpdmUKICAgICAgICAgICAgICAgICAgICAgIC4oZHJpZnRyYXRlID0gbWVkaWFuKGRyaWZ0cmF0ZSwgbmEucm0gPSBUKSksCiAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlKV0gJT4lCiAgIyBtZXJnZSB0byBnZXQgb3RoZXIgcGFyYW1ldGVycyBpbmNsdWRpbmcgYWxsIGRpdmVzCiAgLltkYXRhXzIwMTRbZHJpZnRyYXRlIDwgMCwKICAgICAgICAgICAgICAuKAogICAgICAgICAgICAgICAgIyBtZWRpYW4gZGl2ZSBkdXJhdGlvbiBhbGwgZGl2ZXMgY29uc2lkZXJlZAogICAgICAgICAgICAgICAgZGR1cmF0aW9uID0gbWVkaWFuKGRkdXJhdGlvbiwgbmEucm0gPSBUKSwKICAgICAgICAgICAgICAgICMgbWVkaWFuIG1heCBkZXB0aCBhbGwgZGl2ZXMgY29uc2lkZXJlZAogICAgICAgICAgICAgICAgbWF4ZGVwdGggPSBtZWRpYW4obWF4ZGVwdGgsIG5hLnJtID0gVCksCiAgICAgICAgICAgICAgICAjIG1lZGlhbiBib3R0b20gZGl2ZXMgYWxsIGRpdmVzIGNvbnNpZGVyZWQKICAgICAgICAgICAgICAgIGJvdHR0aW1lID0gbWVkaWFuKGJvdHR0aW1lLCBuYS5ybSA9IFQpCiAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlKV0sCiAgICBvbiA9IGMoIi5pZCIsICJkYXlfZGVwYXJ0dXJlIildCmBgYAoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTMwLCBmaWcuY2FwPSJEcmlmdCByYXRlIHZzLiBCb3R0b20gdGltZSJ9CiMgcGxvdApnZ3Bsb3QoZGF0YVBsb3QsIGFlcyh4ID0gYm90dHRpbWUsIHkgPSBkcmlmdHJhdGUsIGNvbCA9IC5pZCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAuNSwgYWxwaGEgPSAuNSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICBndWlkZXMoY29sb3IgPSAibm9uZSIpICsKICBmYWNldF93cmFwKC5pZCB+IC4pICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA3MDApKSArCiAgbGFicyh4ID0gIkRhaWx5IG1lZGlhbiBCb3R0b20gdGltZSAocykiLCAKICAgICAgIHkgPSAiRGFpbHkgbWVkaWFuIGRyaWZ0IHJhdGUgKG0ucy0xKSIpICsKICB0aGVtZV9qam8oKQpgYGAKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0zMSwgZmlnLmNhcD0iRHJpZnQgcmF0ZSB2cy4gTWF4aW11bSBkZXB0aCJ9CiMgcGxvdApnZ3Bsb3QoZGF0YVBsb3QsIGFlcyh4ID0gbWF4ZGVwdGgsIHkgPSBkcmlmdHJhdGUsIGNvbCA9IC5pZCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAuNSwgYWxwaGEgPSAuNSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsKICBndWlkZXMoY29sb3IgPSAibm9uZSIpICsKICBmYWNldF93cmFwKC5pZCB+IC4pICsKICBsYWJzKHggPSAiRGFpbHkgbWVkaWFuIE1heGltdW0gZGVwdGggKG0pIiwgCiAgICAgICB5ID0gIkRhaWx5IG1lZGlhbiBkcmlmdCByYXRlIChtLnMtMSkiKSArCiAgdGhlbWVfampvKCkKYGBgCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMzIsIGZpZy5jYXA9IkRyaWZ0IHJhdGUgdnMuIERpdmUgZHVyYXRpb24ifQojIHBsb3QKZ2dwbG90KGRhdGFQbG90LCBhZXMoeCA9IGRkdXJhdGlvbiwgeSA9IGRyaWZ0cmF0ZSwgY29sID0gLmlkKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IC41LCBhbHBoYSA9IC41KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogIGd1aWRlcyhjb2xvciA9ICJub25lIikgKwogIGZhY2V0X3dyYXAoLmlkIH4gLikgKwogIGxhYnMoeCA9ICJEYWlseSBtZWRpYW4gRGl2ZSBkdXJhdGlvbiAocykiLCAKICAgICAgIHkgPSAiRGFpbHkgbWVkaWFuIGRyaWZ0IHJhdGUgKG0ucy0xKSIpICsKICB0aGVtZV9qam8oKQpgYGAKCiMjIEJlaGF2aW9yYWwgQWVyb2JpYyBEaXZlIExpbWl0IChiQURMKQoKQmFzZWQgb24gW1NoZXJvIGV0ICphbC4qICgyMDE4KV0oaHR0cHM6Ly93d3cucmVzZWFyY2hnYXRlLm5ldC9wdWJsaWNhdGlvbi8yMjI2ODMwNDJfVG9fYnJlYXRoZV9vcl9ub3RfdG9fYnJlYXRoZV9PcHRpbWFsX2JyZWF0aGluZ19hZXJvYmljX2RpdmVfbGltaXRfYW5kX294eWdlbl9zdG9yZXNfaW5fZGVlcC1kaXZpbmdfYmx1ZS1leWVkX3NoYWdzKSwgd2UgZGVjaWRlZCB0byBsb29rIGF0IHRoZSAqYkFETCogYXMgdGhlIDk1dGggcGVyY2VudGlsZSBvZiBkaXZlIGR1cmF0aW9uIGVhY2ggZGF5LCBmb3IgdGhvc2Ugd2l0aCAkbiBcZ2VxIDgkLiBUaGlzIHRocmVzaG9sZCB3YXMgY2hvc2VuIGZvbGxvd2luZyB0aGlzIGZpZ3VyZSwgcGxlYXNlIG5vdGUgdGhhdCB0aGlzIG51bWJlciBpcyBwYXJ0aWN1bGFybHkgbG93IGNhdXNlIG9ubHkgb25lIGRpdmUgZXZlcnkgMi4yIGhvdXJzIHdhcyBzYW1wbGVkOgoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTM2LCBmaWcuY2FwPSJEaXN0cmlidXRpb24gb2YgdGhlIG51bWJlciBvZiBkaXZlcyBlYWNoIGRheS4gVGhlIHRocmVzaG9sZCB1c2VkIHRvIGNhbGN1bGF0ZSBiQURMIGlzIGZpeGVkIGF0IDUwIGRpdmVzIHBlciBkYXkuIiwgZmlnLmhlaWdodD0zfQpnZ3Bsb3QoZGF0YV8yMDE0WywuKG5iX2RpdmVzID0gLk4pLCAKICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSldLCAKICAgICAgIGFlcyh4PW5iX2RpdmVzLCBmaWxsPS5pZCkpICsKICBnZW9tX2hpc3RvZ3JhbShzaG93LmxlZ2VuZCA9IEZBTFNFKSArIAogIGZhY2V0X3dyYXAoLn4uaWQpICsKICBsYWJzKHk9IiMgb2YgZGF5cyIsIHggPSAiIyBvZiBkaXZlcyBwZXIgZGF5IikgKwogIHRoZW1lX2pqbygpICsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKYGBgCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMzcsIGZpZy5jYXA9IkJlaGF2aW9yYWwgQURMIHZzLiBkcmlmdCByYXRlIGFsb25nIGFuaW1hbHMnIHRyaXAgKEFtIEkgdGhlIG9ubHkgb25lIHNlZWluZyBzb21lIGtpbmQgb2YgcmVsYXRpb25zaGlwPykifQojIHNlbGVjdCBkYXkgdGhhdCBoYXZlIGF0IGxlYXN0IDUwIGRpdmVzCmRheXNfdG9fa2VlcCA9IGRhdGFfMjAxNFssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLihuYl9kaXZlcyA9IC5OKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlKV0gJT4lCiAgLltuYl9kaXZlcyA+PSA4LF0KCiMga2VlcCBvbmx5IHRob3NlIGRheXMKZGF0YV8yMDE0X2NvbXBsZXRlX2RheSA9IG1lcmdlKGRhdGFfMjAxNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXlzX3RvX2tlZXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBjKCIuaWQiLCAiZGF5X2RlcGFydHVyZSIpKQoKIyBkYXRhIHBsb3QKZGF0YVBsb3QgPSBkYXRhXzIwMTRfY29tcGxldGVfZGF5W2RpdmV0eXBlPT0iMTogZm9yYWdpbmciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4oYmFkbCA9IHF1YW50aWxlKGRkdXJhdGlvbiwgMC45NSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpXQoKIyBjb21iaW5lIHR3byBkYXRhc2V0cyB0byBiZSBhYmxlIHRvIHVzZSBhIHNlY29uZCBheGlzCiMgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNDkxODU1ODMvdHdvLXktYXhlcy13aXRoLWRpZmZlcmVudC1zY2FsZXMtZm9yLXR3by1kYXRhc2V0cy1pbi1nZ3Bsb3QyCmRhdGFNZWdhUGxvdCA9IHJiaW5kKGRhdGFfMjAxNF9jb21wbGV0ZV9kYXlbZGl2ZXR5cGUgPT0gIjI6IGRyaWZ0Il0gJT4lCiAgICAgICAgICAgICAgICAgICAgICAgLlssIC4odyA9IC5pZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gZHJpZnRyYXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBkYXlfZGVwYXJ0dXJlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHogPSAic2Vjb25kX3Bsb3QiKV0sCiAgICAgICAgICAgICAgICAgICAgIGRhdGFQbG90WywgLigKICAgICAgICAgICAgICAgICAgICAgICB3ID0gLmlkLAogICAgICAgICAgICAgICAgICAgICAgICMgdHJpY2t5IG9uZQogICAgICAgICAgICAgICAgICAgICAgIHkgPSAoYmFkbCAvIDEwMDApIC0gMSwKICAgICAgICAgICAgICAgICAgICAgICB4ID0gZGF5X2RlcGFydHVyZSwKICAgICAgICAgICAgICAgICAgICAgICB6ID0gImZpcnN0X3Bsb3QiCiAgICAgICAgICAgICAgICAgICAgICldKQoKIyBwbG90CmdncGxvdCgpICsKICBnZW9tX3BvaW50KAogICAgZGF0YSA9IGRhdGFNZWdhUGxvdFt6ID09ICJzZWNvbmRfcGxvdCIsIF0sCiAgICBhZXMoeCA9IHgsIHkgPSB5KSwKICAgIGFscGhhID0gMSAvIDEwLAogICAgc2l6ZSA9IDAuNSwKICAgIGNvbG9yID0gImdyZXk0MCIsCiAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgZ2VvbV9wYXRoKGRhdGEgPSBkYXRhTWVnYVBsb3RbeiA9PSAiZmlyc3RfcGxvdCIsIF0sCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gdyksCiAgICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICAjIEZlYXR1cmVzIG9mIHRoZSBmaXJzdCBheGlzCiAgICBuYW1lID0gIkRyaWZ0IHJhdGUgKG0vcykiLAogICAgIyBBZGQgYSBzZWNvbmQgYXhpcyBhbmQgc3BlY2lmeSBpdHMgZmVhdHVyZXMKICAgIHNlYy5heGlzID0gc2VjX2F4aXMoIH4gKC4gKiAxMDAwKSArIDEwMDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJCZWhhdmlvcmFsIEFlcm9iaWMgRGl2ZSBMaW1pdCAocykiKQogICkgKwogIGxhYnMoeCA9ICIjIGRheXMgc2luY2UgZGVwYXJ0dXJlIikgKwogIGZhY2V0X3dyYXAodyB+IC4pICsKICB0aGVtZV9qam8oKQpgYGAKCj4gTG9va2luZyBhdCB0aGlzIGdyYXBoLCBJIHdhbnQgdG8gYmVsaWV2ZSB0aGF0IHRoZXJlIGlzIHNvbWUga2luZCBvZiByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgKmJBREwqIGFzIGRlZmluZWQgYnkgW1NoZXJvIGV0ICphbC4qICgyMDE4KV0oaHR0cHM6Ly93d3cucmVzZWFyY2hnYXRlLm5ldC9wdWJsaWNhdGlvbi8yMjI2ODMwNDJfVG9fYnJlYXRoZV9vcl9ub3RfdG9fYnJlYXRoZV9PcHRpbWFsX2JyZWF0aGluZ19hZXJvYmljX2RpdmVfbGltaXRfYW5kX294eWdlbl9zdG9yZXNfaW5fZGVlcC1kaXZpbmdfYmx1ZS1leWVkX3NoYWdzKSBhbmQgdGhlIGRyaWZ0IHJhdGUgKGFuZCBzbyBidXlvYW5jeSkuCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMzh9CiMgZ2V0IGJhZGwKZGF0YXBsb3RfMSA9IGRhdGFfMjAxNF9jb21wbGV0ZV9kYXlbLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKGJhZGwgPSBxdWFudGlsZShkZHVyYXRpb24sIDAuOTUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSldCiMgZ2V0IGRyaWZ0cmF0ZQpkYXRhcGxvdF8yID0gZGF0YV8yMDE0X2NvbXBsZXRlX2RheVtkaXZldHlwZSA9PSAiMjogZHJpZnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKGRyaWZ0cmF0ZSA9IG1lZGlhbihkcmlmdHJhdGUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSldCgojIG1lcmdlCmRhdGFQbG90ID0gbWVyZ2UoZGF0YXBsb3RfMSwKICAgICAgICAgICAgICAgICBkYXRhcGxvdF8yLAogICAgICAgICAgICAgICAgIGJ5ID0gYygiLmlkIiwgImRheV9kZXBhcnR1cmUiKSwKICAgICAgICAgICAgICAgICBhbGwgPSBUUlVFKQoKIyBwbG90CmdncGxvdChkYXRhID0gZGF0YVBsb3RbZHJpZnRyYXRlIDwgMCwgXSwgCiAgICAgICBhZXMoeCA9IGJhZGwsIHkgPSBkcmlmdHJhdGUsIGNvbCA9IC5pZCkpICsKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCguaWR+Liwgc2NhbGVzID0gImZyZWUiKSArCiAgbGFicyh4ID0gIkJlaGF2aW9yYWwgQWVyb2JpYyBEaXZlIExpbWl0IChzKSIsCiAgICAgICB5ID0gIkRyaWZ0IHJhdGUgKG0vcykiKSArCiAgdGhlbWVfampvKCkKYGBgCg==